//实现 strStr() 函数。 
//
// 给你两个字符串 haystack 和 needle ，请你在 haystack 字符串中找出 needle 字符串出现的第一个位置（下标从 0 开始）。如
//果不存在，则返回 -1 。 
//
// 
//
// 说明： 
//
// 当 needle 是空字符串时，我们应当返回什么值呢？这是一个在面试中很好的问题。 
//
// 对于本题而言，当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。 
//
// 
//
// 示例 1： 
//
// 
//输入：haystack = "hello", needle = "ll"
//输出：2
// 
//
// 示例 2： 
//
// 
//输入：haystack = "aaaaa", needle = "bba"
//输出：-1
// 
//
// 示例 3： 
//
// 
//输入：haystack = "", needle = ""
//输出：0
// 
//
// 
//
// 提示： 
//
// 
// 0 <= haystack.length, needle.length <= 5 * 104 
// haystack 和 needle 仅由小写英文字符组成 
// 
// Related Topics 双指针 字符串 字符串匹配 
// 👍 1166 👎 0

package com.cute.leetcode.editor.cn;
public class ImplementStrstr {
    public static void main(String[] args) {
        new ImplementStrstr().new Solution().strStr("aabaabaaf", "aabaaf");
    }
    //leetcode submit region begin(Prohibit modification and deletion)

    class Solution {
        /**
         * 使用kmp算法来进行的字符串匹配
         */
        public int strStr(String haystack, String needle) {
            if (needle == null || "".equals(needle)) return 0;
            if ("".equals(haystack)) return -1;
            int[] next = getNext(needle);//获取前缀表
            int len = haystack.length();
            int len2 = needle.length();
            int j = 0;
            for (int i = 0; i < len; i++) {
                //这里是在试图寻找匹配上的前缀
                while (j>0 && haystack.charAt(i)!=needle.charAt(j)) j = next[j-1];
                if (haystack.charAt(i) == needle.charAt(j))//可能一直匹配到j=0，所以这里需要进行一次判断
                    j++;//匹配上j就往前走
                if (j == len2) return i+1-len2;
            }
            return -1;
        }

        /**
         * 获取前缀数组
         * i下标处表示包括i的字符串的最长公共前后缀的长度
         */
        public int[] getNext(String s){
            int[] next = new int[s.length()];
            int j = 0;
            next[0] =0;
            for (int i = 1; i < s.length(); i++) {
                //TODO 这里的j即使前缀末尾下标，又是前缀最长个数
                // j为什么要取到next[j-1]：可以理解为在对j进行匹配，i这个位置是长串
                // 模拟一下aabaaa的前缀和填写过程
                while (j > 0 && s.charAt(i)!=s.charAt(j)) j = next[j-1];
                if (s.charAt(i) == s.charAt(j)) j++;
                next[i] = j;
            }
            return next;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}